package great.project.common.oss2;

import great.project.common.Constants;
import lombok.Getter;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.*;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.Objects;
import java.util.Random;

/**
 * <div  style="border:2px solid red;margin:20px;padding:15px;font-size:24px;text-align:center;color:green;">
 * <p>
 *  阿里云 oss 帮助类，
 *  阿里云简介：
 *      阿里云的oss对象存储，将文件一对象的方式存储到服务器中，我们只需要相关的参数即可进行，存储和读取以及操作
 * <p>
 *     参数解释:
 *      1.bucket 桶，存放数据的一个集合。也可以理解为 一个小组的 ， 简而言之方便管理用的分成组。
 *
 *  </div>
 *
 * @author zhangshun
 * @date 2020/9/25 20:39
 */
@Component
@Scope("prototype")
public class OssHelper2 {

    /**
     * 随机生成的key的前缀
     */
    private static final String PREFIX = "xxxxx";

    /**
     * <div  style="height:10px;width:200px;font-size:15px;text-align:center;color:red;">
     * <p>
     *  appConfig
     *
     *  </div>
     */
    @Getter
    @Resource
    private OssConfiguration ossConfiguration;

    private static final Random RANDOM = Constants.RANDOM;


    /**
     * <div  style="border:2px solid green;margin:20px;padding:15px;font-size:24px;text-align:center;color:red;">
     * <p>
     *  随机的生成一个 文件名字
     *
     *  </div>
     *
     * @param originName 原名
     * @return 生成后的名字
     */
    public static String randomName(String originName) {
        String[] splitArray = originName.split("\\.");
        final String format = LocalDateTime.now(ZoneId.systemDefault()).format(DateTimeFormatter.ofPattern("yyyy_MM_dd'T'HH_mm_ss"));
        return PREFIX + format + "_" + (10000 + RANDOM.nextInt(99999)) + "." + splitArray[splitArray.length - 1];
    }

    /**
     * 将 multipartFile 转换成  临时 file 文件.（该临时文件使用完记得 delete掉.）
     *
     * @param multipartFile multipartFile
     * @return 临时的 file 文件.
     * @throws IOException io
     */
    public static File multipartFileToFile(MultipartFile multipartFile) throws IOException {
        if (multipartFile == null) {
            return null;
        }

        InputStream inputStream = multipartFile.getInputStream();

        File file = new File(Objects.requireNonNull(multipartFile.getOriginalFilename()));
        try {
            OutputStream os = new FileOutputStream(file);
            int bytesRead;
            byte[] buffer = new byte[8192];
            while ((bytesRead = inputStream.read(buffer, 0, 8192)) != -1) {
                os.write(buffer, 0, bytesRead);
            }
            os.close();
            inputStream.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return file;
    }

    /**
     * 默认 创建一个 不会自动关闭的 oss 实例.使用后切忌 调用 {@link OssHelper2Builder#shutdown()} 方法释放 实例。
     * <p>
     * 案例：
     * <p>
     * // 自动关闭 和 不自动关闭的区别 在于 自动关闭的 只能调用一次功能就自动关闭了 不可以像下面这样重复使用， 自动关闭的不需要手动关闭
     * // 创建一个 不会自动关闭的 oss 帮助类
     * OssHelper2Builder ossHelper2Builder = ossHelper2.builder(false);
     * List<Map<String, Object>> fileLists = ossHelper2Builder.getFileList();
     * boolean res = ossHelper2Builder.exist("oss 文件的key");
     * ossHelper2Builder.shutdown();
     * </p>
     *
     * @param autoShutdown 是否自动关闭 oss 实例。 如果自动关闭 则在调用一次方法后直接关闭 oss 实例。
     * @return oss 帮助类 构建类.
     */
    public OssHelper2Builder builder(boolean autoShutdown) {
        return new OssHelper2Builder(ossConfiguration, autoShutdown);
    }

    /**
     * 简单长传文件 随机生成 key 生成规则 为 本类的 {@link #randomName(String)}
     *
     * @param file 文件
     * @return 返回的 key
     * @throws IOException 异常
     */
    public String simpleUpload(File file) throws IOException {
        return builder().uploadFile(null, file, null);
    }

    /**
     * 简单长传文件 随机生成 key 生成规则 为 本类的 {@link #randomName(String)}
     *
     * @param file 文件
     * @return 返回的 key
     * @throws IOException 异常
     */
    public String simpleUpload(MultipartFile file) throws IOException {
        return builder().uploadFile(null, file, null);
    }

    /**
     * 简单长传文件
     *
     * @param key  文件key
     * @param file 文件
     * @return 返回的 key
     * @throws IOException 异常
     */
    public String simpleUpload(String key, File file) throws IOException {
        return builder().uploadFile(key, file, null);
    }

    /**
     * 简单长传文件
     *
     * @param key  文件key
     * @param file 文件
     * @return 返回的 key
     * @throws IOException 异常
     */
    public String simpleUpload(String key, MultipartFile file) throws IOException {
        return builder().uploadFile(key, file, null);
    }

    /**
     * 简单 的 带回调的 长传
     *
     * @param file     文件
     * @param callback 回调
     * @return oss 文件的 key
     * @throws IOException io
     */
    public String simpleCallBackUpload(MultipartFile file, ProgressCallback callback) throws IOException {
        return builder().uploadFile(null, file, callback);
    }

    /**
     * 简单 的 带回调的 长传
     *
     * @param file     文件
     * @param callback 回调
     * @return oss 文件的 key
     * @throws IOException io
     */
    public String simpleCallBackUpload(File file, ProgressCallback callback) throws IOException {
        return builder().uploadFile(null, file, callback);
    }

    /**
     * 简单 的 带回调的 长传
     *
     * @param key      文件key
     * @param file     文件
     * @param callback 回调
     * @return oss 文件的 key
     * @throws IOException io
     */
    public String simpleCallBackUpload(String key, MultipartFile file, ProgressCallback callback) throws IOException {
        return builder().uploadFile(key, file, callback);
    }

    /**
     * 简单 的 带回调的 长传
     *
     * @param key      文件key
     * @param file     文件
     * @param callback 回调
     * @return oss 文件的 key
     * @throws IOException io
     */
    public String simpleCallBackUpload(String key, File file, ProgressCallback callback) throws IOException {
        return builder().uploadFile(key, file, callback);
    }


    /**
     * 默认 创建一个 自动关闭的 oss 实例.
     *
     * @return oss 帮助类 构建类.
     */
    public OssHelper2Builder builder() {
        return builder(true);
    }


}
